package mylibrary.xml.demo.suit;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

/**
 *  <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 *	<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Id="Test" Type="http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml">
 *		<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
 *			<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
 *				<KeyName>ImranAli</KeyName>
 *			</ds:KeyInfo>
 *			<CipherData>
 *				<CipherValue>This is cipher data</CipherValue>
 *			</CipherData>
 *	</EncryptedData>
 *
 * @author gao
 *
 */

public class XmlEncryption {

	private String fileSource = null;
	private String fileResult = null;
			
	private String algoName = null;
	private String keyName = null;
	
	private String encId = null;
	private DocumentBuilder docBuilder = null;
	
	
	public String getFileSource() {
		return fileSource;
	}

	public void setFileSource(String fileSource) {
		this.fileSource = fileSource;
	}

	public String getFileResult() {
		return fileResult;
	}

	public void setFileResult(String fileResult) {
		this.fileResult = fileResult;
	}

	public String getAlgoName() {
		return algoName;
	}

	public void setAlgoName(String algoName) {
		this.algoName = algoName;
	}

	public String getKeyName() {
		return keyName;
	}

	public void setKeyName(String keyName) {
		this.keyName = keyName;
	}

	public String getEncId() {
		return encId;
	}

	public void setEncId(String encId) {
		this.encId = encId;
	}

	public XmlEncryption() {
		try {
			docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private Document getNewDocument() {
		return docBuilder.newDocument();
	}
	
	public void encryptCompleteXmlFile() {
		EncryptedData encDataObj = getEncryptedDataDoc(encId, "DOCUMENT");
		
		Document encMethodDoc = getEncryptionMethodDoc(algoName);
		
		Document encKeyInfoDoc = getKeyInfoDoc(keyName);
		
		String plainData = readFile(fileSource);
		
		String cipherData = getEncryptedData(plainData);
		
		Document cipherDataDoc = getCipherDataDoc(cipherData);
		
		encDataObj.addChild(encMethodDoc);
		encDataObj.addChild(encKeyInfoDoc);
		encDataObj.addChild(cipherDataDoc);
		
		saveEncryptedFile(fileResult, encDataObj.getEncData());
	}
	
	public EncryptedData getEncryptedDataDoc(String id, String encType) {
		EncryptedData ed = new EncryptedData(getNewDocument());
		ed.setId(id);
		if(encType.equals("DOCUMENT")) {
			ed.setType(AlgoNames.DOCUMENT);
		}
		return ed;
	}

	public Document getEncryptionMethodDoc(String algoName) {
		EncryptionMethod em = new EncryptionMethod(this.getNewDocument());
		if(algoName.equals("TripleDes-cbc")) {
			em.setAlgorithm(AlgoNames.TRIPLE_DES);
		}
		return em.getEncMethod();
	}

	public Document getKeyInfoDoc(String keyName) {
		GenericKeyInfo ki = new GenericKeyInfo(this.getNewDocument(), "ds", AlgoNames.XML_DSIG);
		ki.setKeyName(keyName);
		return ki.getKeyInfo();
	}
	
	public String readFile(String fileName) {
		String xml = "";
		try {
			FileInputStream fis = new FileInputStream(fileName);
			byte[] data = new byte[fis.available()];
			fis.read(data);
			xml = new String(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return xml;
	}
	
	public void saveEncryptedFile(String fileName, Document doc) {
		
		//to string
		try {
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer t = tf.newTransformer();
			
			ByteArrayOutputStream bos = new ByteArrayOutputStream();  
            t.transform(new DOMSource(doc), new StreamResult(bos));  
            System.out.println(bos.toString());  
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		
		
	}
	
	public String getEncryptedData(String data) {
		return "This is cipher data";
	}
	
	public Document getCipherDataDoc(String data) {
		CipherData cd = new CipherData(this.getNewDocument());
		cd.setValue(data);
		return cd.getCipherData();
	}
	
	
	
	public static void main(String[] args) {
		
		XmlEncryption xmlEnc = new XmlEncryption();
		xmlEnc.setFileSource("D:\\pom.xml");
		//xmlEnc.setFileResult("EncryptedOrder.xml");
		xmlEnc.setAlgoName("TripleDes-cbc");
		xmlEnc.setKeyName("ImranAli"); 
		xmlEnc.setEncId("Test");
		xmlEnc.encryptCompleteXmlFile();
	}
}
